package com.github.base.aspect;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.TimeInterval;
import cn.hutool.extra.servlet.ServletUtil;
import cn.hutool.json.JSONUtil;
import com.github.base.annotation.SysLog;
import com.github.base.controller.AuthController;
import com.github.base.domain.Log;
import com.github.base.global.Const;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.time.LocalDateTime;

/**
 * 系统日志切面处理类
 *
 * @author hui.zhang
 * @date 2021/1/28 11:04 上午
 */

@Slf4j
@Aspect
@Component
public class SysLogAspect {

    /**
     * 切点
     */
    @Pointcut("@annotation(com.github.base.annotation.SysLog)")
    public void logPointCut() {
    }

    /**
     * 环绕通知
     * @param joinPoint
     */
    @Around("logPointCut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Exception {
        return saveLog(joinPoint);
    }

    /**
     * 保存日志
     * @param joinPoint
     */
    private Object saveLog(ProceedingJoinPoint joinPoint) throws Exception {
        Log sysLog = new Log();
        try {
            TimeInterval timer = DateUtil.timer();

            MethodSignature signature = (MethodSignature) joinPoint.getSignature();

            // 请求方法名
            String className = joinPoint.getTarget().getClass().getName();
            String methodName = signature.getName();
            // 请求的参数
            Object[] args = joinPoint.getArgs();
            String params = JSONUtil.toJsonStr(args);
            // 操作
            Method method = signature.getMethod();
            SysLog syslog = method.getAnnotation(SysLog.class);
            // 注解上的描述
            String action = syslog.value();
            String module = syslog.module();

            RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
            HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
            String ip = ServletUtil.getClientIP(request);

            sysLog.setSuccess(Const.YES);
            sysLog.setIp(ip);
            sysLog.setAction(action);
            sysLog.setModule(module);
            sysLog.setMethod(className + "." + methodName + "()");
            sysLog.setParams(params);
            sysLog.setState(Const.YES);
            sysLog.setCreateTime(LocalDateTime.now());
//            Token token = SubjectUtil.getToken(request);
//            if (ObjectUtil.isNotEmpty(token)) {
//                String userId = token.getUserId();
//                sysLog.setOperator(userId);
//            }


            Object proceed = joinPoint.proceed();

            // 花费毫秒数
            Long time = timer.interval();
            sysLog.setTime(time.toString());
            if (AuthController.class.getName().equals(className)) {
                params = "[{\"*\":\"*\"}]";
            }
            String detail =  "("+ip+")访问:"+className + "." + methodName + "()"+" 传入:"+ params +" 执行:"+action+" 共用时:"+time +"毫秒";
            log.info(JSONUtil.toJsonStr(detail));
            return proceed;
        } catch (Throwable t) {
            log.error(t.getMessage());
            sysLog.setSuccess(Const.NO);
            sysLog.setStackTrace(t.getMessage());
            throw new RuntimeException(t.getMessage());
        } finally {
            sysLog.insert();
        }

    }

}
